﻿using System;
using System.Collections.Generic;
using CSharpConsoleTestSolution.Bean;

namespace CSharpConsoleTestSolution.Demo {
    public class P31_Geniric_partial_enum_structure {
        /**
         * 1.泛型, 时间: 09:45
         * 泛型 (generic)无处不在
         *  ·为什么需要泛型:避免成员膨胀或者类型膨胀
         *  ·正交性: 泛型类型(类/接口/委托/......) 、泛型成员(属性/方法/字段/......)
         *  ·类型方法财维断
         *  ·泛型与委托、lambda表达式
         */
        public static void Generic_test() {
            Console.WriteLine("1.1.泛型");
            Apple apple = new Apple { Color = "Red" };
            Box<Apple> box = new Box<Apple> { Cargo = apple };
            Console.WriteLine(box.Cargo.Color);

            
            Console.WriteLine();
            Console.WriteLine("1.2.两个数组拼接");
            int[] a1 = { 1, 2, 3, 4, 5 };
            int[] a2 = { 1, 2, 3, 4, 5, 6 };
            double[] d1 = { 1.1, 2.2, 3.3, 4.4, 5.5 };
            double[] d2 = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 };
            var result0 = Zip(a1, a2);
            var result1 = Zip(d1, d2);
            var join0 = string.Join(",", result0);
            var join1 = string.Join(",", result1);
            Console.WriteLine($"string.Join: {join0}");
            Console.WriteLine($"string.Join: {join1}");
        }

        private class Box<TCargo> {
            public TCargo Cargo{ get; set; }
        }

        private class Apple {
            public string Color{ get; set; }
        }

        private static T[] Zip<T>(IReadOnlyList<T> a, T[] b) {
            T[] zipped = new T[a.Count + b.Length];
            int ap = 0, bp = 0, zp = 0;
            while (ap < a.Count || bp < b.Length) {
                if (ap < a.Count) zipped[zp++] = a[ap++];
                if (bp < b.Length) zipped[zp++] = b[bp++];
            }
            return zipped;
        }

        
        /**
         * 2.partial 类(public partial class App {}, namespace & className 确保一致), 时间: 59:40
         *  ·减少类的派生
         *  ·partial 类与 Entity Framework (用于数据库实体扩展)
         *  ·partial 类与 Windows Forms,  WPF,  ASP.NET Core
         */
        public static void partial_test() {
            Console.WriteLine();
            Console.WriteLine("2.partial 类");
            Console.WriteLine("创建 Person 类的 partial(Person 要被 partial 修饰):");
            Console.WriteLine("  1.在项目新建Partial目录(非必须), 然后新建类: PersonPart2.cs");
            Console.WriteLine("  2.将 Person 所在的 namespace & className 复制到 ↑, 然后再扩展方法.");
            Person person = new Person("Timothy") { Score = 99 };
            person.setId(1);                    //partial 扩展方法
            var report = person.Report(); //partial 扩展方法
            Console.WriteLine($"report = {report}");
        }

            
        /**
         * 3.enum 枚举, 时间: 1:14:20
         * 枚举类型
         *  ·人为限定取值范围的整数
         *  ·整数值的对应
         *  ·比特位式用法
         */
        public static void enum_test() {
            Console.WriteLine();
            Console.WriteLine("3.enum 枚举");
            Person2 person2 = new Person2 {Id = 0, Name = "Timothy"};
            person2.Level = EnumLevel.Boss;
            person2.Skill = EnumSkill.Drive | EnumSkill.Cook | EnumSkill.Program | EnumSkill.Teach;
            person2.Report();
            Console.WriteLine("Person can Cook: {(person2.Skill & EnumSkill.Cook) == EnumSkill.Cook}");
            Console.WriteLine($"Person can Cook: {(person2.Skill & EnumSkill.Cook) == EnumSkill.Cook}");
        }
        private class Person2 {
            public int Id{ get; set; }
            public string Name{ get; set; }
            public EnumLevel Level{ get; set; }
            public EnumSkill Skill{ get; set; }
            public void Report() {
                Console.Write($"Id={Id}, name={Name}, ");
                Console.Write($"Level={Level}, (int)Level={(int)Level}, ");
                Console.WriteLine($"Skill=\"{Skill}\", (int)Skill={(int)Skill}");
            }
        }

            
        /**
         * 4.struct 结构体(不用new), 时间: 1:30:01
         * 结构体(struct)
         *  ·值类型，可装/拆箱
         *  ·可实现接口，不能派生自类/结构体(不能有基类/基结构体)
         *  ·不能有显式无参构造器, 可以有"全参"构造
         */
        public static void struct_test() {
            Console.WriteLine();
            Console.WriteLine("4.1.struct 结构体(不用new)");
            Struct_Student stu;
            stu.Id = 1;
            stu.Name = "Timothy";
            stu.Score = 99;
            Console.WriteLine(stu.ToString());

            
            Console.WriteLine();
            Console.WriteLine("4.2.赋值: 是完整的copy!");
            Console.WriteLine("Struct_Student stu2 = stu;");
            Struct_Student stu2 = stu;
            stu2.Id = 2;
            stu2.Name = "Michael";
            Console.WriteLine($"stu2: {stu2.ToString()}");
            Console.WriteLine($"stu1: {stu.ToString()}");


            Console.WriteLine();
            Console.WriteLine("4.3.struct 可以实现接口!");
            Console.WriteLine("public struct Struct_Student: ISpeak { }");
            stu.Speak();
            stu2.Speak();
            
            
            Console.WriteLine();
            Console.WriteLine("4.4.struct 不能派生自类/结构体(不能有基类/基结构体)");
            
            
            Console.WriteLine();
            Console.WriteLine("4.5.struct 不能有显式无参构造器, 可以有\"全参\"构造");
        }
    }
}